package settingsapp.ui;


import settingsapp.settings.continuous.ContinuousSettingChanger;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.widget.TextView;
import ece.settingsapp.R;

public class ContinuousChangerActivity extends Activity
{	
	public static final String TAG = ContinuousChangerActivity.class.getSimpleName();
	public final int END_REGION_RADIUS= 75;	
	
	private View.OnTouchListener gListener;
	private GestureDetector gDetector;
	private CCGestureHandler gHandler;
	private int settingValue;
	private Intent myIntent;
	
	
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.continuous_changer);   
        
        View rootView = findViewById(R.id.continouschanger_view);
        initializeGesturing(rootView);      
        
        myIntent = getIntent();
        settingValue = myIntent.getIntExtra(ContinuousSettingChanger.ONSET_INITIAL_VALUE,-1);
        if(settingValue == -1)
        {
        	settingValue = 0;
        	Log.d(TAG,"Failed to retrieve initial setting value.");
        }
        // Set the text
    	TextView text = (TextView)findViewById(R.id.progress_textview);
    	text.setText(""+settingValue+"%");
    }
    
    protected void updateSettingValue(int progress)
    {
    	int rawValue = settingValue*3;
    	
    	rawValue += progress;
    	
    	if(rawValue > 300)
    		rawValue = 300;
    	if(rawValue < 0)
    		rawValue = 0;
    	
    	settingValue = rawValue/3;
    	
    	TextView text = (TextView)findViewById(R.id.progress_textview);
    	text.setText(""+settingValue+"%");
    }
    
    protected void finishButtonPressed()
    {
    	myIntent.putExtra(ContinuousSettingChanger.ONSET_RESULT_VALUE,settingValue);
    	setResult(RESULT_OK, myIntent);    	
    	finish();
    }
            
    private void initializeGesturing(View rootView)
    {
    	gHandler = new CCGestureHandler(this);
    	gDetector = new GestureDetector(getApplicationContext(), gHandler);
    	
        gListener = new View.OnTouchListener() {
        	public boolean onTouch(View v, MotionEvent event) {
             	if (gDetector.onTouchEvent(event)) {
             		return true;
                 }
                 
                 // Check for the ACTION_UP event to know when an action is finished
                 if(event.getAction() == MotionEvent.ACTION_UP)
                 {
                 	gHandler.onUp(event);               	
                 }                
                 
                 return false;
             }
         };                 
         
         rootView.setOnTouchListener(gListener);        
     }
        
    private class CCGestureHandler extends SimpleOnGestureListener
    {   	
    	ContinuousChangerActivity myActivity;
    	double lastAngle;
    	float lastX, lastY, centerX, centerY;
    	
    	boolean posSet = false;    	
    	
    	public CCGestureHandler(ContinuousChangerActivity activity)
    	{
    		myActivity = activity;      		
    	}
    	
    	private double calcAngle(float x, float y)
    	{
    		double angle;    	
    		findCenter();
    		
    		// Find the angle from the center in degrees    		
    		angle = Math.round(Math.atan((x-centerX)/(y-centerY))/Math.PI*180);
    		    		  		
    		return angle;
    	}
    	
    	private int calcProgress(double newAngle, float x, float y)
    	{
    		int progress;    		
    		
    		// Top to bottom transition
    		if(lastY > centerY && (y-centerY) < 0)
    		{
    			if(x >= centerX)
    				progress = (int)Math.round(lastAngle-newAngle+180);   				
    			else
    				progress = (int)Math.round(newAngle-lastAngle+180);     				
    		}
    		// Bottom to top
    		else if(lastY < centerY && y >= centerY)
    		{
    			if(x >= centerX)
    				progress = (int)Math.round(newAngle-lastAngle+180);    				
    			else
    				progress = (int)Math.round(lastAngle-newAngle+180);
    		}
    		// Both are on the same side
    		else
    		{
        			progress = (int) Math.round(lastAngle-newAngle);       	
    		}
    		// TODO
    		if(progress > 20)
    			progress = 1;
    		if(progress < -20)
    			progress = -1;

    		lastX = x;
    		lastY = y;
    		lastAngle = newAngle;    		
    		
    		return progress;
    	}
    	
    	public void findCenter()
    	{
    		// Get the location of the parent view
    		int[] location = new int[2];
    		//View rootView = myActivity.findViewById(R.id.continouschanger_view);
    		View spinnerView = myActivity.findViewById(R.id.spinner_imageview);
    		Log.d(TAG,""+spinnerView.getWidth()+" "+spinnerView.getHeight());
    		// Find the center
    		centerX = (location[0]+spinnerView.getWidth())/2;
    		centerY = (location[1]+spinnerView.getHeight())/2;
    	}
    	
    	public boolean onDown(MotionEvent ev)
    	{

    		
    		if(!posSet)
    		{
    			lastX = ev.getX();
    			lastY = ev.getY();
    			lastAngle = calcAngle(lastX, lastY);
    			posSet = true;
    		}
    		
    		// If this is in the end region bounds, we want to ignore its changes
    		if(!checkWithinEndRegion(ev))
    			update(ev);    		
    		return true;
    	}
    	
    	public boolean onUp(MotionEvent ev)
    	{    		
    		posSet = false;
    		update(ev);
    		if(checkWithinEndRegion(ev))
    			finishButtonPressed();
    		else
    			update(ev);
    		return true;
    	}
    	
    	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
    	{
    		update(e2);
    		return true;
    	}
    	
    	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
    	{
    		update(e2);
    		return true;
    	}
    	
    	private void update(MotionEvent ev)
    	{
    		double angle = calcAngle(ev.getX(),ev.getY());
    		int progress = calcProgress(angle, ev.getX(), ev.getY());
    		updateSettingValue(progress);
    	}
    	
    	private boolean checkWithinEndRegion(MotionEvent ev)
    	{
    		if(Math.hypot(ev.getX()-centerX,ev.getY()-centerY) < END_REGION_RADIUS)
    			return true;
    		return false;    		
    	}
    }
    	
    	
    
}